package ChatRoom;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCPClientFrame extends JFrame implements ActionListener, Runnable {
    // 服务器ip地址的文本框
    private final JTextField tfServerIP = new JTextField();
    // 服务器端口号的文本框
    private final JTextField tfServerPort = new JTextField();
    // 保存聊天信息
    private final JTextArea taTalkMessage = new JTextArea();
    // 发送信息的文本框
    private final JTextField tfSendMessage = new JTextField();
    // 套接字地址对象
    private InetSocketAddress inetSocketAddress = null;
    // 是否客户端主动退出
    private boolean isClientClose = false;
    // 初始化客户端套接字
    private final Socket socket = new Socket();

    public TCPClientFrame() {
        super("聊天室---客户端");
    }

    public void initFrame() {
        try {
            inetSocketAddress = new InetSocketAddress(InetAddress.getLocalHost(), 2000);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        this.getContentPane().setBackground(new Color(240, 240, 240));
        Font defaultFont = new Font("Segue UI", Font.PLAIN, 14);

        // 连接面板
        JPanel connPanel = new JPanel();
        connPanel.setPreferredSize(new Dimension(400, 110));
        connPanel.setBackground(new Color(255, 255, 255));
        connPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
        this.add(connPanel, BorderLayout.NORTH);

        JLabel lblServer = new JLabel("服务器：");
        lblServer.setFont(defaultFont);
        connPanel.add(lblServer);

        tfServerIP.setPreferredSize(new Dimension(260, 30));
        tfServerIP.setText(inetSocketAddress.getAddress().getHostAddress());
        tfServerIP.setFont(defaultFont);
        connPanel.add(tfServerIP);

        // 连接按钮
        JButton btnConn = new JButton("连接");
        btnConn.setActionCommand("conn");
        btnConn.setFont(defaultFont);
        btnConn.setBackground(new Color(80, 180, 15));
        btnConn.setForeground(Color.WHITE);
        btnConn.setFocusPainted(false);
        btnConn.addActionListener(this);
        connPanel.add(btnConn);

        JLabel lblPort = new JLabel("端口号：");
        lblPort.setFont(defaultFont);
        connPanel.add(lblPort);

        tfServerPort.setPreferredSize(new Dimension(260, 30));
        tfServerPort.setText(String.valueOf(inetSocketAddress.getPort()));
        tfServerPort.setFont(defaultFont);
        connPanel.add(tfServerPort);

        // 退出按钮
        JButton btnExit = new JButton("退出");
        btnExit.setActionCommand("exit");
        btnExit.setFont(defaultFont);
        btnExit.setBackground(new Color(235, 135, 10));
        btnExit.setForeground(Color.WHITE);
        btnExit.setFocusPainted(false);
        btnExit.addActionListener(this);
        connPanel.add(btnExit);

        // 服务器信息标签
        String serverInfo = "服务器：" + inetSocketAddress.getHostName() + "  端口号：" + inetSocketAddress.getPort();
        JLabel lblServerInfo = new JLabel(serverInfo);
        lblServerInfo.setFont(defaultFont);
        connPanel.add(lblServerInfo);

        // 信息显示区域
        taTalkMessage.setLineWrap(true);
        taTalkMessage.setWrapStyleWord(true);
        taTalkMessage.setFont(defaultFont);
        taTalkMessage.setBackground(new Color(245, 245, 245));
        taTalkMessage.setEditable(false);  // 禁止编辑
        taTalkMessage.setBorder(BorderFactory.createLineBorder(new Color(180, 180, 180)));
        JScrollPane spTalkMessage = new JScrollPane(taTalkMessage);
        spTalkMessage.setPreferredSize(new Dimension(400, 200));
        spTalkMessage.setBorder(BorderFactory.createEmptyBorder());
        this.add(spTalkMessage, BorderLayout.CENTER);

        // 发送面板
        JPanel sendPanel = new JPanel();
        sendPanel.setPreferredSize(new Dimension(400, 60));
        sendPanel.setBackground(new Color(255, 255, 255));
        sendPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
        this.add(sendPanel, BorderLayout.SOUTH);

        JLabel lblSend = new JLabel("发送：");
        lblSend.setFont(defaultFont);
        sendPanel.add(lblSend);

        tfSendMessage.setPreferredSize(new Dimension(280, 30));
        tfSendMessage.setFont(defaultFont);
        tfSendMessage.setBackground(Color.WHITE);
        tfSendMessage.setBorder(BorderFactory.createLineBorder(new Color(180, 180, 180)));
        sendPanel.add(tfSendMessage);

        // 发送按钮
        JButton btnSend = new JButton("发送");
        btnSend.setActionCommand("send");
        btnSend.setFont(defaultFont);
        btnSend.setBackground(new Color(80, 180, 15));
        btnSend.setForeground(Color.WHITE);
        btnSend.setFocusPainted(false);
        btnSend.addActionListener(this);
        sendPanel.add(btnSend);

        // 设置窗口属性
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setBounds(600, 200, 440, 400);
        this.setVisible(true);

        tfServerIP.requestFocusInWindow();
        tfServerIP.setCaretPosition(tfServerIP.getText().length()); // 设置光标在末尾
    }


    public static void main(String[] args) {
        TCPClientFrame tsf = new TCPClientFrame();
        tsf.changeTalkMessage("请连接服务器...");
        tsf.initFrame();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
        switch (actionCommand) {
            case "send":
                String message = tfSendMessage.getText();
                if (message.length() == 0) {
                    JOptionPane.showMessageDialog(this, "发送的信息不能为空!");
                } else {
                    sendMessage(message, true);
                }
                tfSendMessage.setText("");
                break;
            case "conn":
                try {
                    if (socket != null && socket.isConnected()) {
                        changeTalkMessage("已经连接到服务器！");
                    } else {
                        // 连接服务器
                        assert socket != null;
                        socket.connect(inetSocketAddress);
                        changeTalkMessage("成功连接到服务器！");
                        startRecThread(); // 启动接收信息线程
                    }
                } catch (IOException e1) {
                        e1.printStackTrace();
                    changeTalkMessage("连接服务器失败！");
                }
                break;
            case "exit":
                sendMessage("bye", true);
                changeTalkMessage("正在关闭连接，请稍候...");
                isClientClose = true;
                Timer timer = new Timer(5000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (socket != null && !socket.isClosed()) {
                            try {
                                socket.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                        System.exit(0);// 退出程序
                    }
                });
                timer.setRepeats(false);  // 确保定时器只执行一次
                timer.start();
                break;

        }
    }

    @Override
    public void run() {
        try {
            // 循环接收来自服务器的信息
            while (true) {
                InputStream inputStream = socket.getInputStream();
                byte[] buf = new byte[1024];
                int len = inputStream.read(buf);
                String str = new String(buf, 0, len);

                if ("bye".equals(str)) {
                    if (!isClientClose) {
                        sendMessage("bye", false);
                        changeTalkMessage("服务器已断开连接！");
                    }
                    break;
                }
                // 显示消息
                changeTalkMessage(str);
                Thread.sleep(100);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                    changeTalkMessage("客户端与服务器已断开连接！");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void startRecThread() {
        Thread thread = new Thread(this);
        thread.start();
    }

    private void sendMessage(String message, boolean isPrintMessage) {
        if (socket.isClosed() || !socket.isConnected()) {
            changeTalkMessage("客户端与服务器未连接或已关闭！");
            return;
        }
        byte[] datas = message.getBytes();
        try {
            OutputStream os = socket.getOutputStream();
            os.write(datas);
            if (isPrintMessage) {
                changeTalkMessage("我：" + message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    void changeTalkMessage(String message) {
        SwingUtilities.invokeLater(() -> {
            String temp = taTalkMessage.getText();
            if (temp.length() > 0) {
                taTalkMessage.append("\n");
            }
            taTalkMessage.append(message);
        });
    }
}